package com.jblv.frame.common.handler;

import com.jblv.frame.common.annotation.AuthIgnore;
import com.jblv.frame.common.annotation.BaseParamsIgnore;
import com.jblv.frame.common.constants.BaseConstant;
import com.jblv.frame.common.controller.BaseController;
import com.jblv.frame.common.dto.LoginOperatorDTO;
import com.jblv.frame.common.dto.UserTokenDTO;
import com.jblv.frame.common.message.Result;
import com.jblv.frame.common.params.BaseParams;
import com.jblv.frame.common.utils.RequestHolder;
import com.jblv.frame.common.utils.SysUserAccessTokenUitls;
import com.jblv.frame.common.utils.GsonUtils;
import com.jblv.frame.common.utils.UserTokenUitls;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author happyonion.yangtao
 * @version 1.0
 * @title AuthInterceptor
 * @projectName jblv-frame
 * @packageName com.jblv.common.handler
 * @description 权限拦截类
 * @date Create at 2020/5/8 11:43
 * @since jdk1.8
 */
public class AuthInterceptor extends HandlerInterceptorAdapter {
    private static Logger logger = LoggerFactory.getLogger(AuthInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("======================[ preHandle ]=======================================");
        String url=request.getRequestURL().toString();
        if(!url.matches("(.*)/api/(.*)")){
            return true;
        }
            BaseParams baseParams = null;

        try {
            baseParams = SysUserAccessTokenUitls.getBaseParams(request);
        } catch (Exception var10) {
        }

        Map<String, Object> threadLocalMap = new HashMap();
        if (baseParams != null) {
            threadLocalMap.put("APP_ID", baseParams.getAppId());
        }

        if (handler instanceof HandlerMethod) {
            BaseParamsIgnore authIgnoreAnnotation = (BaseParamsIgnore)((HandlerMethod)handler).getMethodAnnotation(BaseParamsIgnore.class);
            if (authIgnoreAnnotation != null && authIgnoreAnnotation instanceof BaseParamsIgnore) {
                return true;
            }
        }

        if (baseParams == null) {
            this.headformatResponseError(response);
            return false;
        } else {
            if (handler instanceof HandlerMethod) {
                AuthIgnore authIgnoreAnnotation = ((HandlerMethod)handler).getMethodAnnotation(AuthIgnore.class);
                if (authIgnoreAnnotation != null && authIgnoreAnnotation instanceof AuthIgnore) {
                    return true;
                }
            }

            String token = request.getHeader(BaseConstant.TOKEN);
            if (StringUtils.isNotEmpty(token)) {
                UserTokenDTO userTokenDTO = UserTokenUitls.getUserTokenDTO(token);
                Long nowTime = System.currentTimeMillis();
                if (null == userTokenDTO ||  nowTime > userTokenDTO.getExpireTime()){
                    logger.error("token已过期");
                    this.errorResponse(response);
                    return false;
                }
                threadLocalMap.put("token", token);

                String userType = SysUserAccessTokenUitls.getUserType(request);
                threadLocalMap.put(RequestHolder.OPER_USER_TYPE, userType);

                if (userType == "" ) {
                    logger.error("unsupported user type received");
                    this.errorResponse(response);
                    return false;
                }

                LoginOperatorDTO dto = SysUserAccessTokenUitls.getLoginOperatorDTO(request);
                if (dto == null) {
                    logger.error("未登录");
                    this.errorResponse(response);
                    return false;
                }

                threadLocalMap.put(RequestHolder.OPER_USER_ID, dto.getUserId());
                threadLocalMap.put(RequestHolder.OPER_USER_NAME, dto.getUserName());
            }

            String baseParamsStr = request.getHeader(BaseConstant.PARAMS);
            if (StringUtils.isNotEmpty(baseParamsStr)) {
                threadLocalMap.put("request-params", baseParamsStr);
            }
            RequestHolder.add(threadLocalMap);
            return super.preHandle(request, response, handler);
        }
    }

    private void headformatResponseError(HttpServletResponse response) {
        Result<String> authResult = BaseController.renderHeaderError();
        writeResponse(response,authResult);
    }

    private void errorResponse(HttpServletResponse response) {
        Result<String> authResult = BaseController.unloginInvalid();
        writeResponse(response,authResult);
    }

    private void errorResponse(HttpServletResponse response,Result<String> authResult) {

        if (null == authResult){
            authResult = BaseController.unloginInvalid();
        }
        writeResponse(response,authResult);
    }

    private void writeResponse(HttpServletResponse response,  Result<String> authResult){
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");
        try {
            response.getWriter().write(GsonUtils.getJsonStr(authResult));
        } catch (IOException var4) {
            logger.error("发送错误消息失败" + var4.getMessage());
        }
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        logger.info("======================[ afterCompletion ]=======================================");
        RequestHolder.remove();
    }
}
